use gloo_net::http::Request;
use serde::Deserialize;
use serde_json::json;

use super::APP_HOST;

#[derive(Deserialize, Clone, PartialEq)]
pub struct Crate {
  pub id: i32,
  pub rustacean_id: i32,
  pub name: String,
  pub code: String,
  pub version: String,
  pub description: Option<String>,
  pub created_at: String,
}

pub async fn api_crates(token: &str) -> Result<Vec<Crate>, gloo_net::Error> {
  let request_url = format!("{}/crates", APP_HOST);

  let resp = Request::get(&request_url)
    .header("Authorization", &format!("Bearer {}", token))
    .send()
    .await?;

  resp.json::<Vec<Crate>>().await
}

pub async fn api_crates_delete(
  token: &str,
  id: i32,
) -> Result<(), gloo_net::Error> {
  let request_url = format!("{}/crates/{}", APP_HOST, id);

  Request::delete(&request_url)
    .header("Authorization", &format!("Bearer {}", token))
    .send()
    .await?;

  Ok(())
}

pub async fn api_crate_create(
  token: &str,
  name: String,
  code: String,
  rustacean_id: i32,
  version: String,
  description: String,
) -> Result<Crate, gloo_net::Error> {
  let request_url = format!("{}/crate", APP_HOST);

  let resp = Request::post(&request_url)
    .header("Authorization", &format!("Bearer {}", token))
    .header("Accept", "appliction/json")
    .json(&json!({
      "name": name,
      "code": code,
      "rustacean_id": rustacean_id,
      "version": version,
      "description": description
    }))?
    .send()
    .await?;

  resp.json::<Crate>().await
}

pub async fn api_crate_update(
  token: &str,
  id: i32,
  name: String,
  code: String,
  rustacean_id: i32,
  version: String,
  description: String,
) -> Result<Crate, gloo_net::Error> {
  let request_url = format!("{}/crates/{}", APP_HOST, id);

  let resp = Request::put(&request_url)
    .header("Authorization", &format!("Bearer {}", token))
    .json(&json!({
      "name": name,
      "code": code,
      "rustacean_id": rustacean_id,
      "version": version,
      "description": description
    }))?
    .send()
    .await?;

  resp.json::<Crate>().await
}

pub async fn api_crate_show(
  token: &str,
  id: i32,
) -> Result<Crate, gloo_net::Error> {
  let request_url = format!("{}/crates/{}", APP_HOST, id);

  let resp = Request::get(&request_url)
    .header("Authorization", &format!("Bearer {}", token))
    .send()
    .await?;

  resp.json::<Crate>().await
}
